﻿
namespace MyFurion.Application
{
    /// <summary>
    /// 菜单仓储
    /// </summary>
    public class MenuRepository:BaseRepository<MenuInfo>,ITransient
    {
        /// <summary>
        /// 查询条件
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private Expression<Func<MenuInfo, bool>> GetCodition(MenuInfoPage input)
        {
            var exp = Expressionable.Create<MenuInfo>();
            exp.AndIF(!string.IsNullOrWhiteSpace(input.MenuCode), it => it.MenuCode.Contains(input.MenuCode));
            exp.AndIF(!string.IsNullOrWhiteSpace(input.MenuName), it => it.MenuName.Contains(input.MenuName));
            exp.AndIF(input.MenuType.HasValue, it =>it.MenuType==input.MenuType.Value);
            return exp.ToExpression();
        }
        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PageResult<MenuInfo>> GetPageList(MenuInfoPage input)
        {
            var whereExp = GetCodition(input);
            return await GetPageListAsync(whereExp, input.PageIndex, input.PageSize, it => it.CreateTime);
        }
        /// <summary>
        /// 获取数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<List<MenuInfo>> GetDataList(MenuInfoPage input)
        {
            var exp = GetCodition(input);
            return await GetList(exp, it=>it.SortNum, OrderByType.Asc);
        }
        /// <summary>
        /// 获取树数据
        /// </summary>
        /// <returns></returns>
        public async Task<List<MenuInfo>> GetTreeData()
        {
            return await Context.Queryable<MenuInfo>().OrderBy(p => p.SortNum).ToTreeAsync(p => p.Children, p => p.ParentId, null);
        }
        /// <summary>
        /// 根据查询条件获取树结构数据
        /// </summary>
        /// <returns></returns>
        public async Task<List<MenuInfo>> GetTree(MenuInfoPage input)
        {
            bool isNotFilter = ToolUtil.IsPropNull(input, new List<string>() { "PageIndex", "PageSize", "StartTime", "EndTime" });
            if (isNotFilter)
            {
                return await GetTreeData();
            }
            else
            {
                var exp = GetCodition(input);
                var ids = await Context.Queryable<MenuInfo>().Where(exp).Select(p => p.Id).ToListAsync();
                var inIds = ids.Cast<object>().ToArray();
                return await Context.Queryable<MenuInfo>().OrderBy(p => p.SortNum).ToTreeAsync(p => p.Children, p => p.ParentId, null, inIds);
            }
        }
        /// <summary>
        /// 根据父级id获取数据
        /// </summary>
        /// <returns></returns>
        public async Task<List<MenuInfo>> GetByParentId(long pid)
        {
            return await GetList(it => it.ParentId == pid, it => it.SortNum, OrderByType.Asc);
        }
        /// <summary>
        /// 获取菜单操作权限标识
        /// </summary>
        /// <returns></returns>
        public async Task<List<string>> GetActionPer()
        {
            if (CurrentUserInfo.IsSuperAdmin)
            {
                return await Context.Queryable<MenuInfo>().Where(it => it.Status == EnumStatus.Enabled)
                    .Select(it => it.MenuCode).ToListAsync();
            }
            else
            {
                return await Context.Queryable<MenuInfo, RoleMenuInfo, UserRoleInfo>((m, rm, ur) => new JoinQueryInfos
                       (
                        JoinType.Left, m.Id == rm.MenuId,
                        JoinType.Left, rm.RoleId == ur.RoleId
                       ))
                   .Where((m, rm, ur) => ur.UserId == CurrentUserInfo.UserId && m.Status == EnumStatus.Enabled)
                   .Select((m, rm, ur) => m.MenuCode).ToListAsync();
            }
        }
        /// <summary>
        /// 获取用户菜单权限信息
        /// </summary>
        /// <returns></returns>
        public async Task<List<PermissionInfo>> GetMenuPer()
        {
            var menuTreeNodes = new List<PermissionInfo>();
            if (!CurrentUserInfo.IsSuperAdmin)
            {
                //查询权限菜单
                var menuList = await Context.Queryable<MenuInfo, RoleMenuInfo, UserRoleInfo>((m, rm, ur) => new JoinQueryInfos
                        (
                         JoinType.Left, m.Id == rm.MenuId,
                         JoinType.Left, rm.RoleId == ur.RoleId
                        ))
                    .Where((m, rm, ur) => ur.UserId == CurrentUserInfo.UserId && m.Status == EnumStatus.Enabled)
                    .OrderBy((m, rm, ur) => m.SortNum)
                    .Select((m, rm, ur) => m)
                    .ToListAsync();
                var btnList = menuList.Where(g => g.MenuType == EnumMenuType.Button).ToList();
                var menuDatas = menuList.Where(g => g.MenuType != EnumMenuType.Button).ToList();
                //权限树结构数据处理
                List<long> menuIds = menuDatas.Select(g => g.Id).ToList();
                var inIds = menuIds.Cast<object>().ToArray();
                var menuTree = await Context.Queryable<MenuInfo>().OrderBy(p => p.SortNum).ToTreeAsync(it => it.Children, it => it.ParentId, null, inIds);
                //树结构数据转换
                foreach (var item in menuTree)
                {
                    PermissionInfo itemPer = new PermissionInfo();
                    itemPer.MenuName = item.MenuName ?? "";
                    itemPer.MenuUrl = item.MenuUrl ?? "";
                    itemPer.MenuIcon = item.MenuIcon ?? "";
                    itemPer.MenuType = item.MenuType.GetDescription() ?? "";
                    itemPer.BtnPer = btnList.Where(g => g.ParentId == item.Id).Select(g => g.MenuName ?? "").ToList();
                    itemPer.Children = await GetChildrenMenuList(item.Id, item.Children, btnList);
                    menuTreeNodes.Add(itemPer);
                }
            }
            else
            {
                menuTreeNodes = await GetAllPer();
            }
            return menuTreeNodes;
        }
        /// <summary>
        /// 获取所有菜单权限数据
        /// </summary>
        /// <returns></returns>
        public async Task<List<PermissionInfo>> GetAllPer()
        {
            var menuTreeNodes = new List<PermissionInfo>();
            var baseMenuList = await Context.Queryable<MenuInfo>().Where(p => p.Status ==EnumStatus.Enabled && p.MenuType != EnumMenuType.Button)
                   .OrderBy(p =>p.SortNum).ToListAsync();
            var btnList= await Context.Queryable<MenuInfo>().Where(p => p.Status == EnumStatus.Enabled && p.MenuType == EnumMenuType.Button)
                   .OrderBy(p => p.SortNum).ToListAsync();
            var rootMenu = baseMenuList.Where(p => p.ParentId == null).ToList();//获取根节点数据
            foreach (var item in rootMenu)
            {
                PermissionInfo itemPer = new PermissionInfo();
                itemPer.MenuName = item.MenuName ?? "";
                itemPer.MenuUrl = item.MenuUrl ?? "";
                itemPer.MenuIcon = item.MenuIcon ?? "";
                itemPer.MenuType = item.MenuType.GetDescription() ?? "";
                itemPer.BtnPer = btnList.Where(g => g.ParentId == item.Id).Select(g => g.MenuName ?? "").ToList();
                itemPer.Children = await GetChildrenMenuList(item.Id, baseMenuList, btnList);
                menuTreeNodes.Add(itemPer);
            }
            return menuTreeNodes;
        }
        /// <summary>
        /// 获取菜单子节点权限
        /// </summary>
        /// <param name="pid">父级节点id</param>
        /// <param name="menuList">菜单数据</param>
        /// <param name="btnList">按钮数据</param>
        /// <returns></returns>
        private async Task<List<PermissionInfo>> GetChildrenMenuList(long pid, List<MenuInfo> menuList,List<MenuInfo> btnList)
        {
            List<PermissionInfo> childNodes = new();
            var childData = menuList.Where(p => p.ParentId == pid).ToList();
            foreach (var child in childData)
            {
                PermissionInfo itemPer = new PermissionInfo();
                itemPer.MenuName = child.MenuName ?? "";
                itemPer.MenuUrl = child.MenuUrl ?? "";
                itemPer.MenuIcon = child.MenuIcon ?? "";
                itemPer.MenuType = child.MenuType.GetDescription() ?? "";
                itemPer.BtnPer = btnList.Where(g => g.ParentId == child.Id).Select(g => g.MenuName ?? "").ToList();
                itemPer.Children = await GetChildrenMenuList(child.Id, menuList,btnList);
                childNodes.Add(itemPer);
            }
            return childNodes;
        }
        /// <summary>
        /// 根据角色id获取菜单权限集合
        /// </summary>
        /// <param name="roleid"></param>
        /// <returns></returns>
        public async Task<List<MenuInfo>>GetRoleMenuPer(long roleid)
        {
            var menuTree = await GetTreeData();
            var roleMenuIds = await App.GetService<RoleMenuRepository>().GetRoleMenuIdList(new List<long> { roleid});
            if (roleMenuIds.Any())
            {
                SetIsPer(menuTree, roleMenuIds);
            }
            return menuTree;
        }
        /// <summary>
        /// 遍历菜单树节点，设置角色菜单权限
        /// </summary>
        /// <param name="menuTree"></param>
        /// <param name="menuPerIds"></param>
        private void SetIsPer(List<MenuInfo> menuTree,List<long> menuPerIds)
        {
            foreach (var menu in menuTree)
            {
                menu.IsRolePer = menuPerIds.Any(g => menu.Id == g);
                SetIsPer(menu.Children, menuPerIds);
            }
        }
    }
}
